iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0
Vue.js

I need VUE.系列 第 23

Day20. 做個 list 之 key

  • 分享至 

  • xImage
  •  

關於 index

首先我們回顧先前文章 D18. 做個 list 裡提到的 index 索引值,裡面提過它是從 0 開始計算的,但沒有詳細說明到每個 index 跟其所串聯的資料沒有相關性

簡單的說,例如範本裡的 Avicii, Lenka, Shakira 依序顯示出索引值的話會如下所示:

  1. Avicii

  2. Lenka

  3. Shakira

一但透過操作 array 的順序變化或者是增刪,只有資料的順序、內容會變動,索引值會維持原本的順序或值去顯示,並不會產生相對應的行為。

例如移動 Avicii 到最後面,則顯示如下:

  1. Lenka

  2. Shakira

  3. Avicii

若刪除 Shakira 這個值則顯示如下:

  1. Lenka

  2. Avicii

從上面的範例,應該可以明確的理解到,index 只是單純地列出有幾個值( 而且都從 0 開始 ),並不會跟資料建立互相的綁定或產生相依性,就單純做它自己,靜靜地顯示而已。

關於 key

基於 index 不綁定的原因,當程式需要**建立具有相依性以及互相綁定的值時,會使用 key **來建立,它用於使 v-for 不要 loop 出超出預期的狀態。

也就是我們可以預期到使用前列範例去列出 0, 1, 2 的時候,它可以真正的去移動以及被刪增,例如移動 Avicii 到最後面,則顯示如下:

  1. Lenka

  2. Shakira

  3. Avicii

又或刪除 Shakira 這個值可以顯示如下:

  1. Lenka

  2. Avicii

可以觀察到 key 與 data 具有相依性

更詳細的說明可以參考官方網站的說明: Maintaining State with key

超出預期的狀態

先上 code 體驗一下

什麼是超出預期的狀態,前面已經明確地列出 index 與 key 的不同,那麼換個方式來實作,按照課程範例,可以先修改 template 的內容並新增一個 “ move ” 按鈕( 原本的 json 資料結構請不要改動 )。

<ul class="text-left">
  <li v-for="musicDetail in musicDetails" class="mb-3">
    {{ musicDetail.name }} : {{ musicDetail.quote }} <small>{{ musicDetail.from }}</small><br />
    <input type="text" class="w-full"/>
  </li>
</ul>
<button type="button" v-on:click="move" class="border-green-600 m-3">Move to bottom</button>

注意,我有使用 TailWindCSS,所以才會加上一些 class 設定,若是不需要或者要自行加 css 是完全可以的唷!

接著給予相對應的 function 到 methods 裡。

move(){
  const first = this.musicDetails.shift()

  this.musicDetails.push(first)
}

這裡先命名了 first 這個變數來呼叫 array 裡第一個物件的值 ( 在此是指 Avici,它位於 array 裡第一個位置唷 ),再以 shift() 將 Avici 移除掉並把 array 裡第二個物件的值往前移動,也就是說把 Lenca 移動到最前面,這時候 array 就渲染出 Lenca, Shakira,詳請參考 Array.prototype.shift()

接著以 push(first) 來將 Avici 新增到 array 最後面的順序,所以 array 渲染出的就變成 Lenca, Shakira, Avici,詳請參考 Array.prototype.push()

有點難以理解的話,就把 code 貼上去體驗,圖示如下,預設會是

https://ithelp.ithome.com.tw/upload/images/20230924/20140492d1m6NAxg61.png

若是按了按鈕,就會呈現出下圖的變化,Avici 被移動到最下面

https://ithelp.ithome.com.tw/upload/images/20230924/20140492Jvt4wfytjA.png

重點來了!

現在重新整理頁面,讓 Avici 排在最上面,然後在 input 裡隨便打串字,顯示的圖會如下:

https://ithelp.ithome.com.tw/upload/images/20230924/20140492o9In8AaxIg.png

但是!就是這個但是!!!

這個時候如果按了按鈕會讓隨便打的字跟著 Avici 一起跳到下面去嗎?

答案是並不會!!!!

https://ithelp.ithome.com.tw/upload/images/20230924/201404920pdSa44MeM.png

這個看起來奇怪的狀況是因為被操作的是 data 裡的 array ,但寫在 template 裡的東西就如同 index 一樣,跟 array 裡的資料並沒有相依性,所以 input 裡的字並沒有錯,它還是原本那個它並沒有改變,這個狀態有個名詞叫做 “patching”,其目標是為了節省效能,只做資料的操作而不去動到 template ( 也就是 DOM )。

畫了一張圖,如果無法理解,希望圖可以解釋( 如果還是很困惑,請留言給我,我會再想想辦法解釋 )。

https://ithelp.ithome.com.tw/upload/images/20230924/20140492MGANkEiDfb.png

解決這個問題就靠 key

將 template 加上 key 後如下:

<ul class="text-left">
  <li v-for="musicDetail in musicDetails" :key="musicDetail.name" class="mb-3">
    {{ musicDetail.name }} : {{ musicDetail.quote }} <small>{{ musicDetail.from }}</small><br />
    <input type="text" class="w-full"/>
  </li>
</ul>
<button type="button" v-on:click="move" class="border-green-600 m-3">Move to bottom</button>

會使用 name 是因為如同之前文章所提,我貼的範例資料只有 name 是單純的詞,沒有空白唷。

這時候再重新整理頁面並隨便打入字進 input 裡,操作按鈕,就可以順利的看到整個 template 裡的資料與 key 有所綁定了( 會跟著移動 )。

https://ithelp.ithome.com.tw/upload/images/20230924/20140492yyNJhaM6iN.png

點選按鈕後:

https://ithelp.ithome.com.tw/upload/images/20230924/201404920UWsF3QSrK.png

還是要注意

除了巢狀 v-for,其實使用 key 值去綁定資料做操作也是會消耗效能。

目前的我雖然理解了課程的說明,但一時還是不太能完整的描述或找到淺顯易懂的相關文章,因此會建議如果有任何疑問,請盡量讀讀官方文件,或者只在小型的資料切換時去做這個操作,不然在大型的資料操作時會體感到很耗效能( 課程是這樣說的,還沒操作過大型專案的我使用 “我相信你”之術 )。

小結

雖然都是在製作 list 這個 v-for 的題目,課程也只有短短的 20 分鐘,但其實花費了三天的許多時間在這上面,只能說學習是沒有捷徑的,希望我寫的文可以為瀏覽的各位帶來真的淺顯易懂的 Aha moment!

下一篇文章將是進行一個小小迷你專案練習,使用的是從文章開始到目前所學的內容,看起來並不是很困難,應該是可以很好駕馭的,但為了健康的生活作息,還是不那麼緊湊,就順其自然地學習吧。

然後看著剩下的 22 個章節,我想真的飆不完,不過至少可以先完成一個練習專案也不錯,一起加油吧!


上一篇
Day19. 做個 list 之 nested v-for
下一篇
Day21 迷你小專案之 CSS 調整器(上)
系列文
I need VUE.33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言